home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
PROBLEMS
/
PREEMPTER
< prev
next >
Wrap
Internet Message Format
|
1992-04-14
|
18KB
From cmarshall@acorn.co.uk Wed Apr 15 03:48:28 1992
Received: from unido.Germany.EU.net by helpdesk.rus.uni-stuttgart.de (5.52/BelWue-1.0SG(subsidiary))
(for zrzm0111) id AA11509; Wed, 15 Apr 92 03:48:28 MST
Received: from eros.uknet.ac.uk
by mail.Germany.EU.net with SMTP (5.65+/UNIDO-2.1.0.b)
via EUnet for helpdesk.rus.uni-stuttgart.de
id AA28243; Wed, 15 Apr 92 03:49:54 +0200
Received: from acorn.co.uk by eros.uknet.ac.uk with UUCP
id <23398-0@eros.uknet.ac.uk>; Wed, 15 Apr 1992 02:48:15 +0100
Received: from oak.acorn.co.uk by acorn.co.uk (4.1/Am32) id AA29108;
Tue, 14 Apr 92 10:52:30 BST
Date: Tue, 14 Apr 92 10:52:53 +0100
From: cmarshall@acorn.co.uk (Chris Marshall)
To: zrzm0111
Subject: Re: Wanted: Information about the preempter
Message-Id: <29EAB985@cmarshall>
Status: RO
In article <1992Apr13.183936.3762@news.uni-stuttgart.de> you wrote:
>Hi
>
>A few weeks ago, someone told here, that he wrote a tool for preemptive
>multitasking and will public it in comp.binaries.acorn.
>Unfortunatly comp.binaries.acorn is closed for a while. Could someone
>give me informations about the author ?
It's included here...
>thanks
>so long
>MUFTI
>
>ps:
> Shouldn't the moderator of comp.binaries.acorn lay a forward to
> one of the ftp/mail-servers, if he isn't on duty for a long time ?
> The software he gets is not for private Acorn ltd. use .....
We could forward all stuff to Albert at Newcastle. The reasons that
nothing has been posted for a while are as follows:-
a) Phil Colmer is ill at present; he would normally handle
comp.sources.acorn
b) Alan Glover and myself are v. busy right now. I expect to
begin posting things again soon, maybe withing the next week
or two. As for Alan, I don't know. Unfortunately, moderating
comp.*.acorn isn't really seen as part as the 'job' that we
do here, so it has to be a spare time activity.
Chris.
______________________________________________________________________
Chris Marshall cmarshall@acorn.co.uk
>From pc123@phx.cam.ac.uk Tue Feb 25 19:29:59 1992
Received: by oak.acorn.co.uk (4.1/Ai1.6)
id AA11229; Tue, 25 Feb 92 19:29:56 GMT
Received: by acorn.co.uk (4.1/Am32)
id AA13477; Tue, 25 Feb 92 19:29:02 GMT
Received: from phx.cam.ac.uk by eros.uknet.ac.uk via JANET with NIFTP (PP)
id <25975-0@eros.uknet.ac.uk>; Tue, 25 Feb 1992 18:22:59 +0000
Date: Tue, 25 Feb 92 18:22:08 GMT
>From: Pete <pc123@phx.cam.ac.uk>
To: submit@acorn.co.uk
Subject: Code for pre-empting a non-desktop task
Message-Id: <A54D6B55FDE90040@UK.AC.CAMBRIDGE.PHOENIX>
Newsgroups: comp.sources.acorn
Here is the code to demonstrate how you can pre-empt a non-desktop program
without running it in a taskwindow or under FrontEnd, as I promised on c-s-a
recently. The code implements a module which acts a bit like FrontEnd but is a
tinsy bit more efficient in its use of RMA; it should be possible to convert it
for multitasking raytracers or other code you are writing without too much
difficulty.
The module writes all output generated by the program into a circular buffer at
a fixed offset in its workspace - a desktop task then uses the OS_Module call
to find out where the workspace is, and reads data out. The effect is that
text produced by a program is not stored in the RMA, so excessive fragmentation
does not occur. This also implies that this module is only the "business end"
of a complete FrontEnd replacement, and you have to write a desktop client
program as well, to display output produced by a task in a window. I am not
posting the client here, because this source is really for illustration only.
The module also allows the task it is running to be stopped and restarted under
control of the controlling program. This is accomplished by writing various
values into another word at a fixed offset in the module's workspace.
Similarly the module may be asked to kill the program it is pre-empting (never
scheduling it again, and closing all its files) or terminate it (call its exit
handler).
As I wrote Express Assembler, the module is written in Express format. You
shouldn't have too much trouble understanding it, as it does not use any fancy
features.
It is well known that only Quiche Eaters comment their programs well. I have
added a few, but...
...if you find you need help following it, send me mail and I will do my best
to help. Or flame about it on c-s-a instead :-) .
SETTYPE "MODULE"
OBJECT "!YAMU.Initiator"
ORG 0
ASSUME PC,0
ASSUME R12,&10000000
SET VSTR,"1.00"
DD LANGUAGE,0,0,SERVICE,TITLE,HELP,0,0,0,0,0
TITLE DB "Initiator",0
ALIGN
HELP DB "Initiator",9,"`VSTR` (",OSVAR "Sys$Date" RIGHT 6," ",OSVAR "Sys$Year",")",0
ALIGN
TASKDESC
DB "Init",0
ALIGN
LANGUAGE
LOCALS
MOV R11,R0
; Claim memory
MOV R0,#6
LIT R3,WEND-WSTART
SWI "OS_Module"
STR R2,[R12]
STR R12,[R2]
MOV R12,R2
; Initialise variables
MOV R0,#0
ST R0,MEMORYMAPVETOED
ST R0,OUTBUFFERREAD
ST R0,OUTBUFFERWRITE
ST R0,MESSAGES
ST R0,SUSPENDED
ST R0,TERMINATING
ST R0,HANDLESUSED
; Register as Wimp task
MOV R0,#200
LIT R1,&4B534154
ADR R2,TASKDESC
SWI "Wimp_Initialise"
ST R1,TASKHANDLE
; Calculate appropriate (initial) slot size. This is not calculated
; in any special way, it just tries to allocate a reasonable amount
; of space. The newer applications ask the Wimp for more space if
; they run out.
MVN R0,#0
MVN R1,#0
SWI "Wimp_SlotSize"
ADD R0,R0,R1
ADD R0,R0,R2
CMP R0,#512*1024
MOVGE R0,#512*1024
SUBLT R0,R0,#64*1024
CMP R0,#0
MOVLE R0,#16*1024
MVN R1,#0
SWI "Wimp_SlotSize"
; Initialise environment, so that funny things don't happen when the
; background task calls the exit handler, etc. In fact the exit
; handler has to come back into this code in order for us to tidy up.
MOV R0,#6 ; Error handler
ADR R1,ERRORHANDLER
MOV R2,R12
ADR R3,ERRORBUFFER
SWI "OS_ChangeEnvironment"
ADR R0,OLDERRORHANDLER
STMIA R0,{R1-R3}
MOV R0,#11 ; Exit handler
ADR R1,EXITHANDLER
MOV R2,R12
MOV R3,#0
SWI "OS_ChangeEnvironment"
ADR R0,OLDEXITHANDLER
STMIA R0,{R1-R3}
; Set interruption of background task
BL SETCALLAFTER
BL CLAIMVECS
; And start the task off
MOV R0,R11
SWI "OS_Write0" ; This just writes the name of the command
SWI "OS_NewLine" ; run into the output buffer.
MOV R0,R11
SWI "OS_CLI" ; Execute the * command that runs the task.
; This may return, if no application is started. In this case, there
; is an outstanding ticker event to cancel, but apart from that we
; just exit.
ADR R13,USRSTACK
BL CANCELTICKER ; Cancel the descheduling time-out.
BL RELEASEVECS ; Release vectors we have claimed.
B KILLMODULE
MAINLOOP
BL RELEASEVECS ; Must release all vectors before polling.
A
MOV R0,#0
ADR R1,POLLBLOCK
SWI "Wimp_Poll"
TEQ R0,#0
BLNE NONIDLEPOLL
ADR R13,USRSTACK
BL RECEIVEMESSAGES
BNE A
; See whether the output buffer is empty - if not we wait until it
; has been emptied before running the task again.
LD R0,OUTBUFFERREAD
LD R1,OUTBUFFERWRITE
TEQ R0,R1
BNE A
; If the task has been stopped by the controlling task, don't
; reschedule it.
LD R0,SUSPENDED
TEQ R0,#0
BNE A
; Set up conditions for re-entering task
BL SETCALLAFTER ; Create a new CallAfter event
BL CLAIMVECS ; and claim the vectors again.
; If the task is being terminated, get ready to call OS_Exit
LD R0,TERMINATING
TEQ R0,#0
MOV R0,#0
ST R0,TERMINATING
; Back into the task again. When restoring the registers, note that
; the correct method for doing this is very dependent on the current
; processor mode - what is shown is NOT a general way of restoring
; a register dump after an exception.
ADR R0,REGBUF
LDMEQIA R0,{R0-PC}^ ; Restore the task's registers.
LDMIA R0,{R0-R14}
MOV R0,#0
LIT R1,&58454241
MOV R2,#2
SWI "OS_Exit" ; Task is being terminated. Note how we can
; even call OS_Exit "within" a CallBack handler.
; General rubbish to do with being a Wimp task, nothing amazing here.
NONIDLEPOLL
TEQ R0,#17
TEQNE R0,#18
MOVNES PC,R14
LD R0,POLLBLOCK+16
TEQ R0,#0 ; Message_Quit
MOVNES PC,R14
ADR R13,USRSTACK
BL CANCELTICKER
MOV R0,#0
ST R0,OUTBUFFERREAD
ST R0,OUTBUFFERWRITE
; and continue into KILLMODULE, below.
; Code to kill the module off. Nothing here that you don't get in
; other modules, the only point worthy of note is that we hang around
; in this routine until all the characters have been read out of the
; circular buffer.
KILLMODULE
LOCALS
; Restore environment
MOV R0,#6 ; Error handler
ADR R1,OLDERRORHANDLER
LDMIA R1,{R1-R3}
SWI "OS_ChangeEnvironment"
MOV R0,#11 ; Exit handler
ADR R1,OLDEXITHANDLER
LDMIA R1,{R1-R3}
SWI "OS_ChangeEnvironment"
; Write the return code into the message word, for the foreground
; task
LD R0,RETURNCODE
ORR R0,R0,#&80000000
ST R0,MESSAGES
; Now call Wimp_Poll until all the characters have been removed from
; the buffer and the return code has been read
A
MOV R0,#0
ADR R1,POLLBLOCK
SWI "Wimp_Poll"
LD R0,OUTBUFFERREAD
LD R1,OUTBUFFERWRITE
TEQ R0,R1
BNE A
LD R0,MESSAGES
TEQ R0,#0
BNE A
; Finish off as a Wimp task
LD R0,TASKHANDLE
LIT R1,&4B534154
SWI "Wimp_CloseDown"
; Release workspace
MOV R0,#7
MOV R2,R12
SWI "OS_Module"
; Zero private word so RISC OS doesn't free it again!!
LD R0,PRIVATEWORD
MOV R1,#0
STR R1,[R0]
; ExitAndDie to end program and kill module; don't set return code
; as this was set by foreground task.
MOV R0,#0
MOV R1,#0
MOV R2,#0
ADR R3,TITLE
SWI "OS_ExitAndDie"
; Just a standard service call handler. Traps Service_Memory so we
; get to keep the memory that the pre-empted task will run in!
SERVICE
; Nothing to do here except veto attempts by the Wimp to remove all
; our memory - this is tried once at the start.
TEQ R1,#&11 ; Service_Memory
MOVNES PC,R14
STMFD R13!,{R0,R12,R14}
LDR R12,[R12]
LD R0,MEMORYMAPVETOED
TEQ R0,#0
LDMNEFD R13!,{R0,R12,PC}^
MOV R1,#0
MOV R0,#1
ST R0,MEMORYMAPVETOED
LDMFD R13!,{R0,R12,PC}^
; Claim write character (so we redirect the program's output into
; the circular buffer) and open file (so we know what files the
; program has open, so we can close them again if it is killed).
CLAIMVECS
MOV R0,#3 ; WrchV
ADR R1,WRCHV
MOV R2,R12
SWI "OS_Claim"
MOV R0,#&D ; FindV
ADR R1,FINDV
MOV R2,R12
SWI "OS_Claim"
MOVS PC,R14
RELEASEVECS
MOV R0,#3 ; WrchV
ADR R1,WRCHV
MOV R2,R12
SWI "OS_Release"
MOV R0,#&D ; FindV
ADR R1,FINDV
MOV R2,R12
SWI "OS_Release"
MOVS PC,R14
; Schedule a descheduling event.
SETCALLAFTER
MOV R0,#20
ADR R1,INTERRUPT
MOV R2,R12
SWI "OS_CallAfter"
MOVS PC,R14
CANCELTICKER
STMFD R13!,{R0,R1,R14}
ADR R0,INTERRUPT
MOV R1,R12
SWI "OS_RemoveTickerEvent"
LDMFD R13!,{R0,R1,PC}^
WRCHV
STMFD R13!,{R1-R2}
LD R1,OUTBUFFERREAD
LD R2,OUTBUFFERWRITE
ADD R2,R2,#2
BIC R2,R2,#&400
TEQ R1,R2
BLEQ CANCELTICKER
BLEQ SETCALLBACK
LD R1,OUTBUFFERWRITE
ADR R2,OUTBUFFER
STRB R0,[R1,R2]
ADD R1,R1,#1
BIC R1,R1,#&400
ST R1,OUTBUFFERWRITE
LDMFD R13!,{R1-R2}
LDMFD R13!,{PC}^
FINDV
LOCALS
TEQ R0,#0 ; Closing a file
BEQ A
STMFD R13!,{R12}
STMFD R13!,{PC}
MOVS PC,R14
MOV R0,R0 ; Our code is re-entered a word further down, so we waste
; this word.
LDMFD R13!,{R12}
LDMVSFD R13!,{PC}
STMFD R13!,{R2,R3}
ADR R2,HANDLES
LD R3,HANDLESUSED
TEQ R3,#32
MOVEQ R3,#31
STR R0,[R2,R3,LSL #2]
ADD R3,R3,#1
ST R3,HANDLESUSED
LDMFD R13!,{R2,R3}
LDMFD R13!,{PC}^
A
TEQ R1,#0 ; Closing all files
BEQ B
STMFD R13!,{R2,R8,R9,R14}
LD R8,HANDLESUSED
ADR R9,HANDLES
C
TEQ R8,#0
LDMEQFD R13!,{R2,R8,R9,PC}^
LDR R2,[R9],#4
SUB R8,R8,#1
TEQ R1,R2
BNE C
MOV R2,#0
STR R2,[R9,#-4]
LDMFD R13!,{R2,R8,R9,PC}^
B
STMFD R13!,{R0,R14}
MOV R0,#0
ST R0,HANDLESUSED
LDMFD R13!,{R0,PC}^
INTERRUPT
; Remember that we must not corrupt R14svc, so we have to mess about
; with changing processor mode.
STMFD R13!,{R0,R14} ; R14irq goes onto irq stack.
MOVS R0,PC ; Preserve old processor mode.
TEQP PC,#3
MOV R0,R0
STMFD R13!,{R14}
BL SETCALLBACK ; Use CallBack code.
LDMFD R13!,{R14}
TEQP R0,#0
MOV R0,R0
LDMFD R13!,{R0,PC}^
; The following is just standard CallBack code, it restores the
; handler address to its old value before returning to the main
; program loop.
SETCALLBACK
STMFD R13!,{R0-R3,R14}
MOV R0,#7 ; CallBack
ADR R1,CALLBACKHANDLER
MOV R2,R12
ADR R3,REGBUF
SWI "OS_ChangeEnvironment"
ADR R14,OLDCALLBACK
STMIA R14,{R1-R3}
SWI "OS_SetCallBack"
LDMFD R13!,{R0-R3,PC}^
CALLBACKHANDLER
TEQP PC,#0
MOV R0,R0
MOV R0,#7
ADR R1,OLDCALLBACK
LDMIA R1,{R1-R3}
SWI "OS_ChangeEnvironment"
B MAINLOOP
; If we get an error reported, we write it into the circular buffer
; and kill the program.
ERRORHANDLER
MOV R12,R0
MOV R0,#2
ST R0,RETURNCODE
SWI "OS_NewLine"
ADR R0,ERRORBUFFER+8
SWI "OS_Write0"
SWI "OS_NewLine"
ADR R13,USRSTACK
BL CANCELTICKER
BL RELEASEVECS
B KILLMODULE
; If the program exits, we tidy up.
EXITHANDLER
ST R2,RETURNCODE
ADR R13,USRSTACK
BL CANCELTICKER
BL RELEASEVECS
B KILLMODULE
; These messages control the pre-empted task. They allow the
; controlling process to stop and restart it, terminate it (which
; invokes the program's exit handler) and kill it (which will never
; reschedule it, and just closes all its files before shutting down).
RECEIVEMESSAGES
LOCALS
STMFD R13!,{R0,R14}
LD R0,MESSAGES
STMFD R13!,{R0}
TST R0,#&80000000
MOVEQ R0,#0
ST R0,MESSAGES
LDMFD R13!,{R0}
TEQ R0,#1 ; Suspend
BEQ A
TEQ R0,#2 ; Restart
BEQ B
TEQ R0,#3 ; Terminate
BEQ C
TEQ R0,#4 ; Kill
BEQ D
LDMFD R13!,{R0,PC}^
A
MOV R0,#1
ST R0,SUSPENDED
LDMFD R13!,{R0,PC}^
B
MOV R0,#0
ST R0,SUSPENDED
LDMFD R13!,{R0,PC}^
C
MOV R0,#1
ST R0,TERMINATING
LDMFD R13!,{R0,PC}^
D
MOV R9,#0
LD R10,HANDLESUSED
ADR R11,HANDLES
E
TEQ R10,#0
BEQ F
MOV R0,#0
LDR R1,[R11],#4
TEQ R1,#0
ADDNE R9,R9,#1
SWINE "OS_Find"
SUB R10,R10,#1
B E
F
BL CLAIMVECS
SWI "OS_WriteS"
DB 13,10,10,"Killed",13,10,0
ALIGN
MOV R0,R9
ADR R1,ERRORBUFFER
MOV R2,#16
SWI "OS_ConvertCardinal4"
SWI "OS_Write0"
SWI "OS_WriteS"
DB " file(s) closed",13,10,0
ALIGN
BL RELEASEVECS
MOV R0,#2
ST R0,RETURNCODE
B KILLMODULE
DSECT
ORG &10000000
WSTART
PRIVATEWORD ALLOC 4
MESSAGES ALLOC 4 ; Messages are written here by a controlling
; task.
OUTBUFFERREAD ALLOC 4
OUTBUFFERWRITE ALLOC 4
OUTBUFFER ALLOC 1024 ; The output circular buffer
TASKHANDLE ALLOC 4
MEMORYMAPVETOED ALLOC 4
SUSPENDED ALLOC 4
TERMINATING ALLOC 4
HANDLESUSED ALLOC 4
RETURNCODE ALLOC 4
REGBUF ALLOC 4*16
OLDCALLBACK ALLOC 4*3
OLDERRORHANDLER ALLOC 4*3
OLDEXITHANDLER ALLOC 4*3
HANDLES ALLOC 4*32
POLLBLOCK ALLOC 256
ERRORBUFFER ALLOC 256+4+4
ALLOC 64
USRSTACK
WEND
DEND
END